// ignore_for_file: always_specify_types

import 'package:dio/dio.dart';

import 'package:flutter/foundation.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter_project/tool/utils/dz_logger.dart';
import 'package:flutter_project/tool/utils/reg_utils.dart';

import '../interceptors/interceptor_network_debounce.dart';
import 'dart:developer';

typedef DownloadFileCall = void Function((bool success, String path));

/*
 * 网络请求引擎封装，目前使用的是 Dio 框架
 */
class NetworkEngine {
  NetworkEngine() {
    dio = Dio();
    // 设置Dio的转换器
    dio.transformer = BackgroundTransformer(); //Json后台线程处理优化（可选）
    // 设置Dio的拦截器
    dio.interceptors.add(NetworkDebounceInterceptor()); //处理网络请求去重逻辑
    if (!kReleaseMode) {
      dio.interceptors.add(LogInterceptor(
        responseBody: true,
        requestBody: true,
        logPrint: (object) {
          log(object as String);
        },
      )); //默认的 Dio 的 Log 打印
    }
  }
  late Dio dio;

  void setOptions(BaseOptions options) {
    dio.options = options;
  }

  void setInterceptors(List<Interceptor>? interceptors) {
    if (interceptors != null) {
      for (Interceptor iptor in interceptors) {
        dio.interceptors.add(iptor);
      }
    }
  }

  /// 网络请求 Post 请求
  Future<Response> executePost({
    required String path,
    Map<String, dynamic>? params,
    Map<String, String>? paths, //文件
    Map<String, Uint8List>? pathStreams, //文件流
    Map<String, String>? headers,
    ProgressCallback? send, // 上传进度监听
    ProgressCallback? receive, // 下载监听
    CancelToken? cancelToken, // 用于取消的 token，可以多个请求绑定一个 token
  }) async {
    final Map<String, dynamic> map = <String, dynamic>{};

    if (params != null || paths != null || pathStreams != null) {
      //只要有一个不为空，就可以封装参数

      //默认的参数
      if (params != null) {
        map.addAll(params);
      }

      //Flie文件
      if (paths != null && paths.isNotEmpty) {
        for (final MapEntry<String, String> entry in paths.entries) {
          final String key = entry.key;
          final String value = entry.value;

          if (value.isNotEmpty && RegCheckUtils.isLocalImagePath(value)) {
            // 以文件的方式压缩，获取到流对象
            final Uint8List? stream =
                await FlutterImageCompress.compressWithFile(
              value,
              minWidth: 1000,
              minHeight: 1000,
              quality: 80,
            );

            //传入压缩之后的流对象
            if (stream != null) {
              map[key] = MultipartFile.fromBytes(stream,
                  filename: entry.value.split('/').last);
            }
          }
        }
      }

      //File文件流
      if (pathStreams != null && pathStreams.isNotEmpty) {
        for (final MapEntry<String, Uint8List> entry in pathStreams.entries) {
          final String key = entry.key;
          final Uint8List value = entry.value;

          if (value.isNotEmpty) {
            // 以流方式压缩，获取到流对象
            final Uint8List stream =
                await FlutterImageCompress.compressWithList(
              value,
              minWidth: 1000,
              minHeight: 1000,
              quality: 80,
            );

            //传入压缩之后的流对象
            map[key] = MultipartFile.fromBytes(stream, filename: "file_stream");
          }
        }
      }
    }

    /// 有时间重新封装
    final FormData formData = FormData.fromMap(map);
    if (!kReleaseMode) {
      DZLog.d(
          tag: "[NetworkEngine]",
          '单独打印 Post 请求 FromData 参数为：fields:${formData.fields.toString()} files:${formData.files.toString()}');
    }

    return dio.post(
      path,
      data: paths == null ? map : formData,
      options: Options(headers: headers),
      onSendProgress: send,
      onReceiveProgress: receive,
      cancelToken: cancelToken,
    );
  }

  /// 网络请求 Get 请求
  Future<Response> executeGet({
    required String path,
    Map<String, dynamic>? params,
    Map<String, String>? headers,
    Duration? cacheExpiration,
    ProgressCallback? receive, // 请求进度监听
    CancelToken? cancelToken, // 用于取消的 token，可以多个请求绑定一个 token
  }) {
    return dio.get(
      path,
      queryParameters: params,
      options: Options(headers: headers),
      onReceiveProgress: receive,
      cancelToken: cancelToken,
    );
  }

  /// Dio 网络下载
  Future<void> downloadFile({
    required String url,
    required String savePath,
    ProgressCallback? receive, // 下载进度监听
    CancelToken? cancelToken, // 用于取消的 token，可以多个请求绑定一个 token
    DownloadFileCall? callback, // 下载完成回调函数
  }) async {
    try {
      await dio.download(
        url,
        savePath,
        onReceiveProgress: receive,
        cancelToken: cancelToken,
      );
      // 下载成功
      callback?.call((true, savePath));
    } on DioException catch (e) {
      DZLog.e(tag: "[NetworkEngine]", "DioException：$e");
      // 下载失败
      callback?.call((false, savePath));
    }
  }
}
